package com.team16.budgetme;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.team16.budgetme.AccountContent.AccountContentListener;

import android.os.Bundle;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.InputFilter;
import android.text.method.DigitsKeyListener;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;

/**
 * The main activity. Shows the user's accounts and allows them to log transactions, 
 * create new accounts, and view their transaction history.
 *
 */
public class MainActivity extends SherlockFragmentActivity implements AccountContentListener {
    private DataHandler data;
    private ArrayList<Account> accounts;
    private ActionBar actionBar;
    private static int position = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        data = new DataHandler(this);
    }

    @Override
    protected void onStart() {
        super.onStart();

        if (data.isAccountsEmpty()) {
            setContentView(R.layout.no_accounts);
        } else {
            setContentView(R.layout.activity_main);
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
            accounts = data.getAllAccounts();

            SpinnerAdapter adapter = new AccountAdapter(this, android.R.layout.simple_spinner_dropdown_item,
                    accounts);

            OnNavigationListener listener = new OnNavigationListener() {
                @Override
                public boolean onNavigationItemSelected(int position, long itemId) {
                    AccountContent content = new AccountContent();
                    FragmentManager manager = getSupportFragmentManager();
                    FragmentTransaction ft = manager.beginTransaction();
                    ft.replace(R.id.main_activity, content);
                    ft.commit();
                    return true;
                }
            };

            actionBar.setListNavigationCallbacks(adapter, listener);
            actionBar.setSelectedNavigationItem(position);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getSupportMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Intent intent;
        AlertDialog dialog;
        switch (item.getItemId()) {
            case R.id.history_button:
                if (data.isAccountsEmpty()) {
                    Toast toast = Toast
                            .makeText(this, "Need to create account", Toast.LENGTH_SHORT);
                    toast.show();
                    return true;
                } else {
                    intent = new Intent(this, HistoryActivity.class);
                    intent.putExtra("position", position);
                    startActivity(intent);
                    return true;
                }
            case R.id.add_account_button:
                dialog = createAccDialog();
                dialog.show();
                return true;
            case R.id.menu_settings:
            	intent = new Intent(this, SettingsActivity.class);
            	intent.putExtra("position", position);
            	startActivity(intent);
            	return true;
            case R.id.welcome_screen:
            	intent = new Intent(this, Tutorial.class);
            	startActivity(intent);
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    public void onClick(View view) {
        AlertDialog dialog;
        switch (view.getId()) {
            case R.id.add_button:
                dialog = createTranDialog(R.string.income);
                dialog.show();
                break;
            case R.id.sub_button:
                dialog = createTranDialog(R.string.expenditure);
                dialog.show();
                break;
            default:
                break;
        }
    }
    
    /**
     * Implemented method of the AccountContentListener interface. Allows AccountContent to get account data.
     */
    @Override
    public Account getAccount() {
        if (actionBar.getSelectedNavigationIndex() >= 0) {
            position = actionBar.getSelectedNavigationIndex();
        }
        return accounts.get(position);
    }

    /**
     * Creates a dialog for creating accounts.
     * 
     * @return The dialog.
     */
    private AlertDialog createAccDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = getLayoutInflater();
        View layout = inflater.inflate(R.layout.add_account_dialog, null);
        final EditText nameView = (EditText) layout.findViewById(R.id.account_name);
        final EditText balanceView = (EditText) layout.findViewById(R.id.current_balance);
        
        /**
         * Filter input amounts to XXXXXX.XX
         */
        balanceView.setFilters(new InputFilter[] {
        		new DigitsKeyListener(Boolean.FALSE, Boolean.TRUE) {
        			int beforeDecimal = 6, afterDecimal = 2;
        			
        			@Override
        			public CharSequence filter(CharSequence source, int start, int end, 
        					Spanned dest, int Astart, int Aend) {
        				String temp = balanceView.getText() + source.toString();
        				
        				if (temp.equals(".")) {
        					return "0.00";
        				}
        				else if (temp.toString().indexOf(".") == -1) {
        					if(temp.length() > beforeDecimal) {
        						return "";
        					}
        				}
        				else {
        					temp = temp.substring(temp.indexOf(".") + 1);
        					if (temp.length() > afterDecimal) {
        						return "";
        					}
        				}
        				return super.filter(source, start, end, dest, Astart, Aend);
        			}
        		}
        });

        builder.setTitle(R.string.add_account).setView(layout)
                .setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String accountName = nameView.getText().toString();
                        String balanceStr = balanceView.getText().toString();
                        if (accountName.matches("") || balanceStr.matches("")) {
                            return;
                        }
                        BigDecimal balance = new BigDecimal(balanceStr);
                        newAccount(accountName, balance);
                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        return builder.create();
    }

    /**
     * Creates a dialog for creating transactions.
     * 
     * @param id The id of the button pressed.
     * @return The dialog.
     */
    private AlertDialog createTranDialog(final int id) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LayoutInflater inflater = getLayoutInflater();
        View layout = inflater.inflate(R.layout.transaction_dialog, null);
        final EditText text = (EditText) layout.findViewById(R.id.transaction_amount);
        /**
         * Filter input amounts to XXXXXX.XX
         */
        text.setFilters(new InputFilter[] {
        		new DigitsKeyListener(Boolean.FALSE, Boolean.TRUE) {
        			int beforeDecimal = 6, afterDecimal = 2;
        			
        			@Override
        			public CharSequence filter(CharSequence source, int start, int end, 
        					Spanned dest, int Astart, int Aend) {
        				String temp = text.getText() + source.toString();
        				
        				if (temp.equals(".")) {
        					return "0.00";
        				}
        				else if (temp.toString().indexOf(".") == -1) {
        					if(temp.length() > beforeDecimal) {
        						return "";
        					}
        				}
        				else {
        					temp = temp.substring(temp.indexOf(".") + 1);
        					if (temp.length() > afterDecimal) {
        						return "";
        					}
        				}
        				return super.filter(source, start, end, dest, Astart, Aend);
        			}
        		}
        });
        
        final Spinner categories = (Spinner) layout.findViewById(R.id.transaction_category);
        ArrayAdapter<String> spinnerAdapter = null;
        
        if(id == R.string.income) {
            categories.setVisibility(View.GONE);
            spinnerAdapter = new ArrayAdapter<String>(this, 
                    android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.incomes));
        } else if(id == R.string.expenditure) {
            spinnerAdapter = new ArrayAdapter<String>(this, 
                    android.R.layout.simple_spinner_dropdown_item, getResources().getStringArray(R.array.expenditures));
        }
        categories.setAdapter(spinnerAdapter);
        
        builder.setTitle(id).setCancelable(true).setView(layout)
                .setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String strAmount = text.getText().toString();
                        String category = (String) categories.getSelectedItem();
                        if (strAmount.matches("")) {
                            return;
                        }
                        BigDecimal amount = new BigDecimal(strAmount);
                        int type = 0;
                        if (id == R.string.income) {
                            type = 1;
                        } else if (id == R.string.expenditure) {
                            type = 0;
                        }
                        newTransaction(amount, type, category);
                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

        return builder.create();
    }

    /**
     * Takes input from dialog, bundles it into an Account object and saves it
     * to the database.
     * 
     * @param name
     * @param balance
     */
    private void newAccount(String name, BigDecimal balance) {
        Account account = new Account();
        account.setBalance(balance);
        account.setName(name);

        data.saveAccount(account);
        
        if(!(accounts == null)) {
            position = accounts.size();
        }
        
        this.onStart();
    }

    /**
     * Takes input from dialog, bundles it into a Transaction object and saves
     * it to the database.
     * 
     * @param amount
     * @param type
     */
    private void newTransaction(BigDecimal amount, int type, String category) {
        SimpleDateFormat dateFormat = (SimpleDateFormat) DateFormat.getDateInstance();
        Date date = new Date();
        Transaction transaction = new Transaction();

        transaction.setAmount(amount);
        transaction.setType(type);
        transaction.setAccount(accounts.get(position).getName());
        transaction.setCategory(category);
        transaction.setDate(dateFormat.format(date));

        data.saveTransaction(transaction);
        this.onStart();
    }

    private class AccountAdapter extends ArrayAdapter<Account> implements SpinnerAdapter {
        private Context context;
        private List<Account> accounts;
        private int resource;

        public AccountAdapter(Context context, int resource, List<Account> accounts) {
            super(context, resource, accounts);
            this.context = context;
            this.accounts = accounts;
            this.resource = resource;
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflator = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View layout = inflator.inflate(resource, parent, false);
            Account a = accounts.get(position);
            TextView name = (TextView) layout.findViewById(android.R.id.text1);
            name.setText(a.getName());
            return layout;
        }
    }
}
